#include "stdafx.h"
#include "SceneBase.h"

#include <QtGui/QPainter>
#include <QtOpenGL/QtOpenGL>

#include <GL/gl.h>

#ifndef GL_MULTISAMPLE
#define GL_MULTISAMPLE  0x809D
#endif

#include <metaioSDK/IMetaioSDKWin32.h>
#include <metaioSDK/GestureHandler.h>


SceneBase::SceneBase(QObject *parent) :
	QGraphicsScene(parent),
	m_bAutoRefresh(false),
	m_initialized(false),
	m_pGestureHandler(0),
	m_pMetaioSDK(0),
	m_viewportWidth(0),
	m_viewportHeight(0)
{
}


SceneBase::~SceneBase()
{
	// Shut down SDK instance here. If you register your own sensors component, make sure you
	// delete it after these lines:
	/*if (m_pMetaioSDK)
	{
		m_pMetaioSDK->registerCallback(0);
		m_pMetaioSDK->registerSensorsComponent(0);
	}*/

	delete m_pMetaioSDK;

	delete m_pGestureHandler;
}


void SceneBase::drawBackground(QPainter* painter, const QRectF& rect)
{
	// Just in case recursive repaint issues reappear at some point, make sure it doesn't crash the
	// application.
	if (!painter->paintEngine())
	{
		qCritical("SceneBase: Recursive repaint, will not render");
		return;
	}

	painter->save();
	if (painter->paintEngine()->type() != QPaintEngine::OpenGL2)
	{
		qCritical("SceneBase: drawBackground needs a QGLWidget to be set as viewport on the graphics view");
		return;
	}

	const unsigned int viewportWidth = (unsigned int)std::max(0, (int)rect.width());
	const unsigned int viewportHeight = (unsigned int)std::max(0, (int)rect.height());

	if (!m_initialized)
	{
		m_bAutoRefresh = true;
		m_pMetaioSDK = metaio::CreateMetaioSDKWin32();
		m_pMetaioSDK->initializeRenderer((int)viewportWidth, (int)viewportHeight, metaio::ESCREEN_ROTATION_0, metaio::ERENDER_SYSTEM_OPENGL_EXTERNAL);

		auto cameras = m_pMetaioSDK->getCameraList();
		printf("Cameras count: %d\n", cameras.size());
		for (uint i = 0; i != cameras.size(); i++)
		{
			printf("Trying Camera %d ...\n", i);
			if (m_pMetaioSDK->startCamera(cameras[i])) 
			{
				printf("Cameras info: %s\n", cameras[i].toString().c_str());
				break;
			}
		}

		// Start first found camera
		//m_pMetaioSDK->startCamera();
		// before using setImage(), should setCameraParameters() for kinecct sensor v2
		//m_pMetaioSDK->setCameraParameters(metaio::Path::fromFSEncoding("Assets/CameraParameters_KinectDefault.xml"), metaio::ECT_TRACKING);

		// Listen to onSDKReady and other events that we may want to handle
		m_pMetaioSDK->registerCallback(this);

		m_initialized = true;

		m_pGestureHandler = new metaio::GestureHandler(m_pMetaioSDK);

		afterMetaioSDKInitialized();

		// Ensure widget sizes are correct
		onAfterSetSceneRect(sceneRect());

		// At this point, the SDK and its renderer is initialized. Since we registered ourself as
		// callback, we will receive the onSDKReady event next, and load our content there.
	}

	if (m_viewportWidth != viewportWidth || m_viewportHeight != viewportHeight)
	{
		m_pMetaioSDK->resizeRenderer((int)viewportWidth, (int)viewportHeight);

		m_viewportWidth = viewportWidth;
		m_viewportHeight = viewportHeight;
	}

	// Enable anti-aliasing
	glPushAttrib(GL_ENABLE_BIT);
	glEnable(GL_MULTISAMPLE);
	glEnable(GL_LINE_SMOOTH);

	//core.RecognizeOneFrame();
	performRendering();

	glPopAttrib();

	// Trigger an update at least every 20 milliseconds, change this if you need higher FPS, or no
	// continuous rendering
	QTimer::singleShot(20, this, SLOT(update()));

	painter->restore();

	// This is a workaround to render the web pages correctly
	glDisable(GL_CULL_FACE);
	glDisable(GL_DEPTH_TEST);
}


void SceneBase::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
	super::mouseMoveEvent(mouseEvent);
}


void SceneBase::mousePressEvent(QGraphicsSceneMouseEvent* mouseEvent)
{
	super::mousePressEvent(mouseEvent);
}


void SceneBase::mouseReleaseEvent(QGraphicsSceneMouseEvent* mouseEvent)
{
	super::mouseReleaseEvent(mouseEvent);
}


void SceneBase::onSDKReady()
{
	loadContent();
}

void SceneBase::recognizeManually()
{
	if (m_bAutoRefresh)
		return;

	const unsigned int viewportWidth = (unsigned int)std::max(0, (int)sceneRect().width());
	const unsigned int viewportHeight = (unsigned int)std::max(0, (int)sceneRect().height());

	if (!m_initialized)
	{
		m_pMetaioSDK = metaio::CreateMetaioSDKWin32();
		m_pMetaioSDK->initializeRenderer((int)viewportWidth, (int)viewportHeight, metaio::ESCREEN_ROTATION_0, metaio::ERENDER_SYSTEM_NULL);

		auto cameras = m_pMetaioSDK->getCameraList();
		printf("Cameras count: %d\n", cameras.size());
		for (uint i = 0; i != cameras.size(); i++)
		{
			printf("Trying Camera %d ...\n", i);
			if (m_pMetaioSDK->startCamera(cameras[i]))
			{
				printf("Cameras info: %s\n", cameras[i].toString().c_str());
				break;
			}
		}

		// Start first found camera
		//m_pMetaioSDK->startCamera();
		// before using setImage(), should setCameraParameters() for kinecct sensor v2
		//m_pMetaioSDK->setCameraParameters(metaio::Path::fromFSEncoding("Assets/CameraParameters_KinectDefault.xml"), metaio::ECT_TRACKING);

		// Listen to onSDKReady and other events that we may want to handle
		m_pMetaioSDK->registerCallback(this);

		m_initialized = true;

		m_pGestureHandler = new metaio::GestureHandler(m_pMetaioSDK);

		afterMetaioSDKInitialized();

		// Ensure widget sizes are correct
		onAfterSetSceneRect(sceneRect());

		// At this point, the SDK and its renderer is initialized. Since we registered ourself as
		// callback, we will receive the onSDKReady event next, and load our content there.
	}

	if (m_viewportWidth != viewportWidth || m_viewportHeight != viewportHeight)
	{
		m_pMetaioSDK->resizeRenderer((int)viewportWidth, (int)viewportHeight);

		m_viewportWidth = viewportWidth;
		m_viewportHeight = viewportHeight;
	}

	//core.RecognizeOneFrame();
	performRendering();

	QTimer::singleShot(20, this, SLOT(recognizeManually()));
}
